/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package explorer;

import compare.CompareUnited;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;

/**
 *
 * @author user1
 */
public final class ExplorerUnited {
    
    public static int modeExplore = 0;
        public static final int EXPLORE_DFS = 0;
        public static final int EXPLORE_BFS = 1;
        
    public static int modeSearch = 0;
        public static final int SEARCH_BRUTEFORCE = 0;
        public static final int SEARCH_KMP = 1;
        public static final int SEARCH_BOYERMOORE = 2; 
    
    public static File startDir;
    public static ArrayList<FileUnited> result = new ArrayList<FileUnited>();

    public static void setExplore(int e) {
        modeExplore = e;
    }
    
    public static void setSearch(int s) {
        modeSearch = s;
    }
    
    public static void setDir(String[] dir) throws FileNotFoundException {
        startDir = new File(dir[0]);
    }
    
    
    private static List<File> exploreDFS(File dir, String pattern) throws FileNotFoundException {
        List<File> list = new ArrayList<File>();
        File[] subdir = dir.listFiles();
        FileUnited fileUnited;
        List<File> fileDir = Arrays.asList(subdir);
        StringTokenizer frase;
        File f;
        int pass = 0;
        //for (File f : fileDir) {
        while (pass < fileDir.size()) {
            f = fileDir.get(pass);
            //list.add(f);
            if (!f.isFile()) {
                List<File> deeperList = exploreDFS(f, pattern);
                list.addAll(deeperList);
            } else if (FileUnited.fileValidator(f)) {
                fileUnited = new FileUnited(f);
                frase = new StringTokenizer(pattern);
                inspectToken(frase, fileUnited);
            }
            ++pass;
        }
        return list;
    }
    
    private static void exploreBFS(File dir, String pattern) throws FileNotFoundException {
        List<File> list = new ArrayList<File>();
        File[] subdir = dir.listFiles();
        FileUnited fileUnited;
        List<File> fileDir = Arrays.asList(subdir);
        StringTokenizer frase;
        File f;
        int pass = 0;
        list.addAll(fileDir);
        //for (File f : fileDir) {
        while (pass < list.size()) {
            f = list.get(pass);
            //list.add(f);
            if (!f.isFile()) {
                subdir = f.listFiles();
                List<File> deeperList = Arrays.asList(subdir);
                list.addAll(deeperList);
            } else if (FileUnited.fileValidator(f)) {
                fileUnited = new FileUnited(f);
                frase = new StringTokenizer(pattern);
                inspectToken(frase, fileUnited);
            }
            ++pass;
        }
    }
    
    public static void inspectToken(StringTokenizer frase, FileUnited fileUnited) {
        String token;
        boolean found = false;
        int i, startchar = -1;
        while (frase.hasMoreTokens()) {
            token = frase.nextToken();
            switch (modeSearch) {
                case SEARCH_BRUTEFORCE:
                    found = CompareUnited.compareBruteForce(token,fileUnited.getName()) != CompareUnited.NOT_FOUND;
                    startchar = CompareUnited.compareBruteForce(token, fileUnited.getContent());
                break;
                case SEARCH_KMP:
                    found = CompareUnited.compareKMP(token,fileUnited.getName()) != CompareUnited.NOT_FOUND;
                    startchar = CompareUnited.compareKMP(token, fileUnited.getContent());
                break;
                case SEARCH_BOYERMOORE:
                    found = CompareUnited.compareBoyerMoore(token,fileUnited.getName()) != CompareUnited.NOT_FOUND;
                    startchar = CompareUnited.compareBoyerMoore(token, fileUnited.getContent());
                break;
                default:
                break;
            }
            i = 0;
            if (found || (startchar != CompareUnited.NOT_FOUND)) {
                found = false;
                while(!found && i < result.size()) {
                        if (result.get(i).getName().equals(fileUnited.getName()) && result.get(i).getExtension().equals(fileUnited.getExtension())) {
                            found = true;
                        } else {
                            i++;
                        }
                    }
                if (!found) {
                    result.add(new FileUnited(fileUnited));
                    result.get(result.size()-1).setStartChar(startchar);
                    startchar=-1;
                } else {
                    result.get(i).setStartChar(startchar);
                    startchar=-1;
                }
            }
        }
    }

    public static void startExplore(String[] pattern) throws FileNotFoundException {
        validateDirectory(startDir);
        result.clear();
        switch (modeExplore) {
            case EXPLORE_DFS:
                exploreDFS(startDir, pattern[0]);
                break;
            case EXPLORE_BFS:
                exploreBFS(startDir, pattern[0]);
                break;
            default:
                break;
        }
    }
    

    /**
     * Directory is valid if it exists, does not represent a file, and can be read.
     */
    static private void validateDirectory(File dir) throws FileNotFoundException {
        if (dir == null) {
            throw new IllegalArgumentException("Directory should not be null.");
        }
        if (!dir.exists()) {
            throw new FileNotFoundException("Directory does not exist: " + dir);
        }
        if (!dir.isDirectory()) {
            throw new IllegalArgumentException("Is not a directory: " + dir);
        }
        if (!dir.canRead()) {
            throw new IllegalArgumentException("Directory cannot be read: " + dir);
        }
    }
}
